#include "sys/Memory.h"
#include "sys/TLB.h"
#include "NOW.h"
#include "sys/IO.h"
static void Log(const char *format, ...){
    va_list args;
    va_start(args, format);          // 初始化va_list
    vfprintf(stdout,format, args);  // 将参数传递给vfprintf
    va_end(args);   
}
int Load(int pid, unsigned int Vaddr, int T){
    Process *proc = &jobs[pid];
    
    unsigned physical_address;

    // 调用 MMU 地址转换函数
    if (get_physical_address(pid, Vaddr, MEM_READ, &physical_address, T)) {
        printf("[%d] Load from virtual address %#x succeeded. Physical: %#x\n", T, Vaddr, physical_address);
        return 1;
    } else {
        printf("[%d] Load failed: segment fault or page fault at %#x\n", T, Vaddr);
        return 0;
    }
   return 1;
}

int Store(int pid, unsigned int Vaddr, int T){
    Process *proc = &jobs[pid];

    // 获取虚拟页号
    unsigned vpn = Vaddr / PAGE_SIZE;
    PageTableEntry *entry = &proc->PTB->e[vpn];

    // 如果是页表项有效且（指向的frame对象所属pid不同 or ref>1），则触发 Copy-on-Write
    if (proc->PTB->e[vpn].v){
        unsigned ppn = proc->PTB->e[vpn].PPN;
        if (frame_table[ppn].pid!=pid){//子程序
            int vic = victim_frame(pid,0);
            if (vic==-1){
                Log("[%d]Error: Invalid victim_frame in Store child copy parent frame!\n",T);
            }
            release_frame(vic, T);
            //Copy 父frame;
            frame_table[vic].pid = pid;
            frame_table[vic].VPN = vpn;
            frame_table[vic].blk = frame_table[ppn].blk;
            frame_table[vic].ref = 1;
            frame_table[vic].refSrc = NULL;
            //修改页表项指向新frame
            proc->PTB->e[vpn].PPN = vic;
            TLB_delE(pid,vpn,T);
            //修改父frame去掉指向源
            --frame_table[ppn].ref;
            del_specific_frame_refSrc(&frame_table[ppn].refSrc,pid,vpn);
            Log("[%d] Store:Process %d's page table entry %d now refers from %#x to %#x(Copy on write)\n",T,pid,vpn,ppn,vic);
        }else if (frame_table[ppn].ref>2){//父程序
            //让下一个子选项“继承”（其copy-on-write，继承除父的指向关系，父删只剩其一个）
            VPI nxt = pop_frame_refSrc(&frame_table[ppn].refSrc);
            VPI *srchead=frame_table[ppn].refSrc;
            int vic = victim_frame(nxt.pid,0);
            if (vic==-1){
                Log("[%d]Error: Invalid victim_frame in Store child copy parent frame!\n",T);
            }
            release_frame(vic, T);
            frame_table[vic].pid = nxt.pid;
            frame_table[vic].VPN = nxt.VPN;
            frame_table[vic].blk = frame_table[ppn].blk;
            frame_table[vic].ref = frame_table[ppn].ref-1;
            frame_table[vic].refSrc = srchead;
            //迁移其它指向该frame的pageTableEntry
            jobs[nxt.pid].PTB->e[nxt.VPN].PPN = vic;
            TLB_delE(nxt.pid,nxt.VPN,T);
            while (srchead){
                jobs[srchead->pid].PTB->e[srchead->VPN].PPN = vic;
                TLB_delE(srchead->pid,srchead->VPN,T);
                srchead = srchead->next;
            }
            //删减父的frame
            frame_table[ppn].ref = 1;
            frame_table[ppn].refSrc = NULL;
            Log("[%d] Store:Process %d transfer references to its frame %#x to %#x(Copy on write)\n",T,pid,ppn,vic);
        }
    }

    // 正常进行地址转换
    unsigned physical_address;
    if (!get_physical_address(pid, Vaddr, MEM_WRT, &physical_address, T)) {
        printf("[%d] Store failed: invalid write access at %#x\n", T, Vaddr);
        return 0;
    }
    TLB_setd(pid, vpn, T);

    printf("[%d] Store to virtual address %#x succeeded. Physical: %#x\n", T, Vaddr, physical_address);
    return 1;
}